package cn.jia.stomp.stompController;

import cn.jia.stomp.pojo.Greeting;
import cn.jia.stomp.pojo.HelloMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @Author: jia
 * @Descirption:
 * @Date: 2018/4/25 9:54
 * @Modified By:
 */

@Controller
public class GreetingController {
    @Autowired
    private SimpMessageSendingOperations sendingOperations;
    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;
    @RequestMapping(value = {"", "test"})
    public String test() {
        return "stomp";
    }

    /**
     * @Author: jia
     * @Date: 2018/4/25 10:06
     * @Modified By: jia
     * @Descirption: 使用@MessageMapping注解
     */
    //@MessageMapping这个注解就表示greeting()方法能够处理指定目的地上到达的消息
    //这个消息发送的目的地为：/server/app/hello,其中/app是隐含的
    @MessageMapping("/hello")
    //该注解可以不写，默认情况下发送到/topic/stomp目的地
    @SendTo("/topic/greetings")
    //由于我们现在处理的不是http，所以不能用spring的HTTPMessageConverter实现转换Greeting对象
    //所以需要使用Jacson来转化
    public Greeting greeting(HelloMessage message) throws Exception {
        System.out.println("来自客户端：" + message.getName());
        System.out.println("连接成功！");
        return new Greeting("你好客户端，我是@MessageMapping：/hello" + message.getName() + "!");
    }

    /**
     * @Author: jia
     * @Date: 2018/4/25 10:07
     * @Modified By: jia
     * @Descirption: 使用@SubcriptionMapping注解处理订阅
     */
    //@SubscribeMapping注解 的方法来处理 对 "/app/macro" 目的地订阅
    // （与 @MessageMapping类似，"/app" 是隐含的 ）；
    //和上面的方法比较，没有事先的访问：即@MessageMapping("/hello")，只有事先访问这个地址的
    //才会sendTo出去，但是这个注解直接回返回出去，只要是订阅了这个地址的订阅者
    //这个注解他不会经过代理，直接返回结果，但是如果加了sento的话就会发送到指定的目的地，这样
    //就会经过代理
    @SubscribeMapping("/marco")
    //如果使用了@SendTo，必然经过代理，客户端首先订阅的是/marco，然后服务器将其相应给了代理，客户端
    //就需要通过其他的方式监听代理
    //@SendTo("/topic/marco")//使用该注解，如果客户端订阅的消息是/marco，则会执行此方法，但是客户端的方法不会执行
    //因为返回的结果发给了sendTo中设置的代理中了
    public Greeting handleSubsciption() {
        Greeting greeting = new Greeting();
        greeting.setMessage("你好客户端，我是@subcribleMapping ! /marco");
        return greeting;
    }

    //在应用的任意地方发送消息,通过地址栏输入访问该地址
    //测试地址：http://localhost:8080/feed?greeting=你好
    @RequestMapping("feed")
    public void sendOnAnyway(@RequestParam("greeting") String greeting) {
        String text = "发送消息给你，我修改了页面内容，请更新！" + greeting;
        Greeting greeting1 = new Greeting();
        greeting1.setMessage(text);
        this.sendingOperations.convertAndSend("/topic/feed", greeting1);
    }

    //发送给指定的用户方式一：
    //发送消息到指定的用户,只有认证通过的用户才能接受，虽然有订阅了此
    //目的地的消费者，但必须是认证通过的
    @MessageMapping("/authen")
    @SendToUser("/queue/authen")
    public Greeting handleSubscriptionByAuthen(HelloMessage message) {
        //首先通过@MessageMapping注解访问时，会携带发送的参数，通过参数
        //判断该用户是否存在，但是不能使用@SubscribeMapping注解的方法发送给特定的用户，
        //因为携带不了有关用户的信息
        //如果使用SpringSecurity认证的话，只有在认证通过时才能调用此方法，这里为了方便，只是做了简单的判断
        Greeting greeting = new Greeting();
        if ("admin".equals(message.getuId())) {
            greeting.setMessage("你好客户端，我是用户认证 ！");
        }
        return greeting;

    }
    //发送给指定的用户方式二：
    //在应用的任意地方发送消息
    //测试地址：http://localhost:8080/sendOnAnywayByAuthen?uId=admin
    @RequestMapping("sendOnAnywayByAuthen")
    public void sendOnAnywayByAuthen(HelloMessage message) {
        if("admin".equals(message.getuId())){
            String text = "发送消息给你，我修改了页面内容，请更新！" + message.getuId();
            Greeting greeting1 = new Greeting();
            greeting1.setMessage(text);
            this.simpMessagingTemplate.convertAndSendToUser(message.getuId(),"/queue/authenOnAnyway", greeting1);
            System.out.println();
        }

    }

    //处理消息异常
    @MessageExceptionHandler(NullPointerException.class)
    //给指定用户回应一个错误
    @SendToUser("/queue/errors")
    public String handleException(Throwable t){
        System.out.println(t.getMessage());
        return t.getMessage();
    }



}
